Skip to content

Conversation

@mauke
Copy link
Contributor

@mauke mauke commented Apr 15, 2025

Why broken? Because haystack/needle are effectively macros (they expand to token sequences), so a call like

Perl_instr(a + b, x ? y : z)

expands to

strstr((char *)a + b, (char *)x ? y : z)

which is just wrong.

Normally I'd simply add the missing parentheses ((char *)(haystack), etc), but it's not clear to me why the casts were added in the first place (and fairly recently, too, in commit 4e52881).

Background:

instr() was originally implemented in pre-standard C (without const and without a prototype) in util.c, perl-1.0. The consts were added fairly early on in 08105a9 (1997): char * instr(register const char *big, register const char *little);

The hand-written C code was replaced by a call to strstr() in 5d1d68e. It cast away const from the arguments to strstr() for no reason I can see: strstr() takes pointers to const char (just like Perl_instr), so the pointers were immediately implicitly re-consted by the prototype of strstr().

Commit fea1d2d straight up turned instr() into an alias for strstr(), which was apparently fine without any casts for 4.5 years. The C code in Perl_instr() was moved from util.c to mathoms.c in commit 534dad4.


  • This set of changes does not require a perldelta entry.

Why broken? Because haystack/needle are effectively macros (they expand
to token sequences), so a call like

    Perl_instr(a + b, x ? y : z)

expands to

    strstr((char *)a + b, (char *)x ? y : z)

which is just wrong.

Normally I'd simply add the missing parentheses ((char *)(haystack),
etc), but it's not clear to me why the casts were added in the first
place (and fairly recently, too, in commit 4e52881).

Background:

instr() was originally implemented in pre-standard C (without const and
without a prototype) in util.c, perl-1.0. The consts were added fairly
early on in 08105a9 (1997): char *
instr(register const char *big, register const char *little);

The hand-written C code was replaced by a call to strstr() in
5d1d68e. It cast away const from the arguments to strstr() for no
reason I can see: strstr() takes pointers to const char (just like
Perl_instr), so the pointers were immediately implicitly re-consted by
the prototype of strstr().

Commit fea1d2d straight up turned instr() into an alias for strstr(),
which was apparently fine without any casts for 4.5 years. The C code in
Perl_instr() was moved from util.c to mathoms.c in commit 534dad4.
@khwilliamson
Copy link
Contributor

The only reason I can think of for the casts is that some platform complained at the time. It could have just been carelessness

@mauke mauke merged commit 6a35e68 into Perl:blead Apr 17, 2025
34 checks passed
@mauke mauke deleted the fix-broken-cast-instr branch April 17, 2025 05:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants